package com.dropdb.demo.service.impl;

import com.dropdb.demo.bean.*;
import com.dropdb.demo.bean.bo.GrouponRuleCreateBO;
import com.dropdb.demo.bean.vo.BaseData;
import com.dropdb.demo.bean.vo.CouponListData;
import com.dropdb.demo.bean.vo.CouponListElementtData;
import com.dropdb.demo.bean.vo.GrouponRecordVO;
import com.dropdb.demo.mapper.*;
import com.dropdb.demo.service.PromotionService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Period;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author qugr
 * @create 2020-06-26 16:57
 */
@Service
public class PromotionServiceImpl implements PromotionService {

    @Autowired
    AdMapper adMapper;

    @Override
    public BaseData queryAds(Integer page, Integer limit, String name, String content, String sort, String order) {
        AdExample adExample = new AdExample();
        AdExample.Criteria criteria = adExample.createCriteria();
        if (name != null) {
            criteria.andNameLike("%" + name + "%");
        }
        if (content != null) {
            criteria.andContentLike("%" + content + "%");
        }
        adExample.setOrderByClause(sort + " " + order);
        PageHelper.startPage(page,limit);
        List<Ad> ads = adMapper.selectByExample(adExample);
        Long total = new PageInfo<>(ads).getTotal();
        return new BaseData(ads,total);
    }

    @Override
    public int insertAd(Ad ad) {
        ad.setAddTime(new Date());
        ad.setUpdateTime(new Date());
        return adMapper.insertSelective(ad);
    }

    @Override
    public Ad queryAd(Integer id) {
        return adMapper.selectByPrimaryKey(id);
    }

    @Override
    public int deleteAd(Integer id) {
        return adMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int updateAd(Ad ad) {
        ad.setUpdateTime(new Date());
        return adMapper.updateByPrimaryKey(ad);
    }

    /**
     * 优惠券管理
     */
    @Autowired
    CouponMapper couponMapper;
    @Autowired
    CouponUserMapper couponUserMapper;

    @Override
    public BaseData queryCoupons(Integer page, Integer limit, String name, Short type, Short status, String sort, String order) {
        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria = couponExample.createCriteria();
        if (name != null) {
            criteria.andNameLike("%" + name + "%");
        }
        if (type != null) {
            criteria.andTypeEqualTo(type);
        }
        if (status != null) {
            criteria.andStatusEqualTo(status);
        }
        couponExample.setOrderByClause(sort + " " + order);
        PageHelper.startPage(page,limit);
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);
        Long total = new PageInfo<>(coupons).getTotal();
        return new BaseData(coupons,total);
    }

    @Override
    public int insertCoupon(Coupon coupon) {
        coupon.setAddTime(new Date());
        coupon.setUpdateTime(new Date());
        return couponMapper.insertSelective(coupon);
    }

    @Override
    public Coupon queryCoupon(Integer id) {
        return couponMapper.selectByPrimaryKey(id);
    }

    @Override
    public int deleteCoupon(Integer id) {
        return couponMapper.deleteByPrimaryKey(id);
    }

    @Override
    public BaseData queryCouponUsers(Integer page, Integer limit, Integer couponId, Integer userId, Short status, String sort, String order) {
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        criteria.andCouponIdEqualTo(couponId);
        if (userId != null) {
            criteria.andUserIdEqualTo(userId);
        }
        if (status != null) {
            criteria.andStatusEqualTo(status);
        }
        couponUserExample.setOrderByClause(sort + " " + order);
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(couponUserExample);
        Long total = new PageInfo<>(couponUsers).getTotal();
        return new BaseData(couponUsers,total);
    }

    @Override
    public int updateCoupon(Coupon coupon) {
        coupon.setUpdateTime(new Date());
        return couponMapper.updateByPrimaryKey(coupon);
    }


    /**
     * 专题管理
     */
    @Autowired
    TopicMapper topicMapper;

    @Override
    public BaseData queryTopics(Integer page, Integer limit, String title, String subtitle, String sort, String order) {
        TopicExample topicExample = new TopicExample();
        TopicExample.Criteria criteria = topicExample.createCriteria();
        if (title != null) {
            criteria.andTitleLike("%" + title + "%");
        }
        if (subtitle != null) {
            criteria.andSubtitleLike("%" + subtitle + "%");
        }
        topicExample.setOrderByClause(sort + " " + order);
        PageHelper.startPage(page,limit);
        List<Topic> topics = topicMapper.selectByExampleWithBLOBs(topicExample);
        Long total = new PageInfo<>(topics).getTotal();
        return new BaseData(topics,total);
    }

    @Override
    public int insertTopic(Topic topic) {
        topic.setAddTime(new Date());
        topic.setUpdateTime(new Date());
        return topicMapper.insertSelective(topic);
    }

    @Override
    public Topic queryTopic(Integer id) {
        return topicMapper.selectByPrimaryKey(id);
    }

    @Override
    public int deleteTopic(Integer id) {
        return topicMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int updateTopic(Topic topic) {
        topic.setUpdateTime(new Date());
        return topicMapper.updateByPrimaryKey(topic);
    }

    /**
     * 团购规则管理
     */
    @Autowired
    GrouponRulesMapper grouponRulesMapper;
    @Autowired
    GrouponMapper grouponMapper;

    @Override
    public BaseData queryGrouponRules(Integer page, Integer limit, Integer goodsId, String sort, String order) {
        GrouponRulesExample grouponRulesExample = new GrouponRulesExample();
        if (goodsId != null) {
            grouponRulesExample.createCriteria().andGoodsIdEqualTo(goodsId);
        }
        grouponRulesExample.setOrderByClause(sort + " " + order);
        PageHelper.startPage(page,limit);
        List<GrouponRules> grouponRules = grouponRulesMapper.selectByExample(grouponRulesExample);
        Long total = new PageInfo<>(grouponRules).getTotal();
        return new BaseData(grouponRules,total);
    }

    @Override
    public int deleteGrouponRule(Integer id) {
        return grouponRulesMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insertGrouponRule(Goods goods, GrouponRuleCreateBO grouponRuleBO) {
        GrouponRules grouponRules = new GrouponRules();
        grouponRules.setGoodsId(goods.getId());
        grouponRules.setGoodsName(goods.getName());
        grouponRules.setPicUrl(goods.getPicUrl());
        grouponRules.setDiscount(grouponRuleBO.getDiscount());
        grouponRules.setDiscountMember(grouponRuleBO.getDiscountMember());
        grouponRules.setAddTime(new Date());
        grouponRules.setUpdateTime(new Date());
        grouponRules.setExpireTime(grouponRuleBO.getExpireTime());
        int insert = grouponRulesMapper.insertSelective(grouponRules);
        grouponRuleBO.setId(grouponRules.getId());
        return insert;
    }

    @Override
    public GrouponRules queryGrouponRule(Integer id) {
        return grouponRulesMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateGrouponRule(Goods goods, GrouponRules grouponRule) {
        grouponRule.setGoodsId(goods.getId());
        grouponRule.setGoodsName(goods.getName());
        grouponRule.setPicUrl(goods.getPicUrl());
        grouponRule.setUpdateTime(new Date());
        int update = grouponRulesMapper.updateByPrimaryKey(grouponRule);
        return update;
    }

    @Autowired
    OrderGoodsMapper orderGoodsMapper;
    @Autowired
    GoodsMapper goodsMapper;

    @Override
    public BaseData queryGroupon(Integer page, Integer limit, Integer goodsId, String sort, String order) {
        GrouponExample grouponExample = new GrouponExample();
        if (goodsId != null) {
            grouponExample.createCriteria().andGrouponIdEqualTo(goodsId);
        }
        PageHelper.startPage(page,limit);
        grouponExample.setOrderByClause(sort + " " + order);
        List<GrouponRecordVO> grouponRecords = new ArrayList<>();
        List<Groupon> groupons = grouponMapper.selectByExample(grouponExample);
        for (Groupon groupon : groupons) {
            GrouponRecordVO grouponRecordVO = new GrouponRecordVO();
            grouponRecordVO.setGroupon(groupon);
            OrderGoodsExample orderGoodsExample = new OrderGoodsExample();
            orderGoodsExample.createCriteria().andOrderIdEqualTo(groupon.getOrderId());
            List<OrderGoods> orderGoods = orderGoodsMapper.selectByExample(orderGoodsExample);
            grouponRecordVO.setGoods(goodsMapper.selectByPrimaryKey(orderGoods.get(0).getGoodsId()));
            grouponRecordVO.setRules(grouponRulesMapper.selectByPrimaryKey(groupon.getRulesId()));
            grouponRecords.add(grouponRecordVO);
        }
        Long total = new PageInfo<>(groupons).getTotal();
        return new BaseData(grouponRecords,total);
    }



    //前台功能
    @Autowired
    CouponMultiTableMapper couponMultiTableMapper;

    @Autowired
    CartMapper cartMapper;

    @Autowired
    JdbcTemplate jdbcTemplate;
    /**
     * checkout时选择优惠券
     * @param userId
     * @return
     */
    @Transactional
    @Override
    public List<CouponListElementtData> selectCouponList(Integer userId, Integer cartId) {
        //先去除过期优惠券，将endtime小于当前时间的行设置status为2
        CouponUserExample couponUserExample = new CouponUserExample();
        couponUserExample.createCriteria()
                .andEndTimeLessThan(new Date())
                .andUserIdEqualTo(userId);
        CouponUser couponUser = new CouponUser();
        couponUser.setStatus((short) 2);
        couponUserMapper.updateByExampleSelective(couponUser, couponUserExample);

        //计算checkout总价
        BigDecimal amount = null;
        if (0 == cartId) {
            String sql = "select sum(`price` * `number`) as `amount` from `cskaoyanmall_cart` where `deleted` = 0 and `checked` = 1 and `user_id` = ?";
            amount = jdbcTemplate.queryForObject(sql, new Object[]{userId}, BigDecimal.class);
        } else {
            CartExample cartExample = new CartExample();
            cartExample.createCriteria()
                    .andIdEqualTo(cartId)
                    .andDeletedEqualTo(false);
            List<Cart> carts = cartMapper.selectByExample(cartExample);
            if (null == carts || 1 != carts.size()) { //没有这个cartId
                return null;
            }
            Cart cart = carts.get(0);
            amount = cart.getPrice().multiply(new BigDecimal(cart.getNumber()));
        }

        return couponMultiTableMapper.selectlist(userId, 0, amount);
    }

    /**
     * 领取优惠券
     * @param userId
     * @param couponId
     * @return
     */
    @Transactional(isolation = Isolation.SERIALIZABLE)
    @Override
    public int receiveCoupon(Integer userId, Integer couponId) {
        //去除过期优惠券，将endtime小于当前时间的行设置status为1
        setExpiredCouponStatus();
        Coupon coupon;

        //判断是否满足领券条件
        coupon = couponMapper.selectByPrimaryKey(couponId);
        if (null == coupon || 0 != coupon.getStatus() || coupon.getDeleted()) {
            return -1; //不存在该优惠券，返回错误-1
        }
        if (0 != coupon.getType()) {
            return -2; //非通用券不能领，返回错误-2
        }
        CouponUserExample couponUserExample = new CouponUserExample();
        couponUserExample.createCriteria()
                .andUserIdEqualTo(userId)
                .andCouponIdEqualTo(couponId);
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(couponUserExample);

        //如果该用户没有领过优惠券，则不需要检测limit字段
        //如果该用户已经领过多张相同的优惠券，证明limit字段为0，同样不需要检测
        if (null != couponUsers && 1 == couponUsers.size() && 1 == coupon.getLimit()) {
            return -3; //已经领过优惠券，返回错误-3
        }

        CouponUser couponUser = new CouponUser();
        couponUser.setUserId(userId);
        couponUser.setCouponId(couponId);
        couponUser.setAddTime(new Date());
        couponUser.setUpdateTime(couponUser.getAddTime());
        couponUser.setStatus((short) 0);

        //判断优惠券的过期方式，设置couponUser的起止时间
        if (0 == coupon.getTimeType()) { //领取时间为起始时间
            couponUser.setStartTime(couponUser.getAddTime());
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(couponUser.getStartTime());
            calendar.add(Calendar.DATE, coupon.getDays());
            couponUser.setEndTime(calendar.getTime());
        } else {
            couponUser.setStartTime(coupon.getStartTime());
            couponUser.setEndTime(couponUser.getEndTime());
        }

        //写入数据库并返回结果
        if (0 < coupon.getTotal()) { //默认值是0代表无限张
            Coupon couponNext = new Coupon();
            couponNext.setId(coupon.getId());
            int total = coupon.getTotal() - 1;
            couponNext.setTotal(total);
            if (0 == total) { //没有优惠券了，下架
                coupon.setStatus((short) 2);
            }
            couponMapper.updateByPrimaryKeySelective(coupon);
        }
        return couponUserMapper.insertSelective(couponUser);
    }

    /**
     * 使用code兑换优惠券
     * @param userId
     * @param code
     * @return
     */
    @Transactional(isolation = Isolation.SERIALIZABLE)
    @Override
    public int exchangeCoupon(Integer userId, String code) {
        setExpiredCouponStatus();

        //判断是否满足领券条件
        CouponExample couponExample = new CouponExample();
        couponExample.createCriteria()
                .andCodeEqualTo(code)
                .andStatusEqualTo((short) 0)
                .andDeletedEqualTo(false);
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);
        if (null == coupons || 0 == coupons.size()) {
            return -1; //不存在该优惠券，返回错误-1
        }
        if (1 != coupons.size()) {
            return -10; //后台添加优惠券出现逻辑错误导致存在多张同code的优惠券，不能领取，返回错误-10
        }
        Coupon coupon = coupons.get(0);
        if (2 != coupon.getType()) {
            return -2; //非兑换券，返回错误-2
        }
        CouponUserExample couponUserExample = new CouponUserExample();
        couponUserExample.createCriteria()
                .andUserIdEqualTo(userId)
                .andCouponIdEqualTo(coupon.getId());
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(couponUserExample);

        //如果该用户没有领过优惠券，则不需要检测limit字段
        //如果该用户已经领过多张相同的优惠券，证明limit字段为0，同样不需要检测
        if (null != couponUsers && 1 == couponUsers.size() && 1 == coupon.getLimit()) {
            return -3; //已经领过优惠券，返回错误-3
        }

        CouponUser couponUser = new CouponUser();
        couponUser.setUserId(userId);
        couponUser.setCouponId(coupon.getId());
        couponUser.setAddTime(new Date());
        couponUser.setUpdateTime(couponUser.getAddTime());
        couponUser.setStatus((short) 0);

        //判断优惠券的过期方式，设置couponUser的起止时间
        if (0 == coupon.getTimeType()) { //领取时间为起始时间
            couponUser.setStartTime(couponUser.getAddTime());
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(couponUser.getStartTime());
            calendar.add(Calendar.DATE, coupon.getDays());
            couponUser.setEndTime(calendar.getTime());
        } else {
            couponUser.setStartTime(coupon.getStartTime());
            couponUser.setEndTime(couponUser.getEndTime());
        }
        //写入数据库并返回结果
        if (0 < coupon.getTotal()) { //默认值是0代表无限张
            Coupon couponNext = new Coupon();
            couponNext.setId(coupon.getId());
            int total = coupon.getTotal() - 1;
            couponNext.setTotal(total);
            if (0 == total) { //没有优惠券了，下架
                coupon.setStatus((short) 2);
            }
            couponMapper.updateByPrimaryKeySelective(coupon);
        }
        return couponUserMapper.insertSelective(couponUser);
    }

    /**
     * 查看我的优惠券，分为3个状态：未使用0，已使用1，已经
     * @param userId
     * @param status
     * @param page
     * @param size
     * @return
     */
    @Override
    public CouponListData myCouponList(Integer userId, Integer status, Integer page, Integer size) {
        PageHelper.startPage(page, size);
        List<CouponListElementtData> selectlist = couponMultiTableMapper.selectlist(userId, status, null);
        PageInfo<CouponListElementtData> pageInfo = new PageInfo<>(selectlist);
        long count = pageInfo.getTotal();
        return new CouponListData(count, selectlist);
    }

    /**
     * 获取可以领取的优惠券
     * @param userId
     * @param page
     * @param size
     * @return
     */
    @Transactional(isolation = Isolation.SERIALIZABLE)
    @Override
    public CouponListData couponList(Integer userId, Integer page, Integer size) {
        setExpiredCouponStatus();
        PageHelper.startPage(page, size);
        List<CouponListElementtData> list = couponMultiTableMapper.list(userId);
        long count = new PageInfo<>(list).getTotal();
        return new CouponListData(count, list);
    }

    private void setExpiredCouponStatus() {
        //去除过期优惠券，将endtime小于当前时间的行设置status为1
        CouponExample couponExample = new CouponExample();
        couponExample.createCriteria()
                .andEndTimeLessThan(new Date());
        Coupon coupon = new Coupon();
        coupon.setStatus((short) 1);
        couponMapper.updateByExampleSelective(coupon, couponExample);
    }
}
